"""
用户画像服务
实现用户个性化服务，包括用户画像管理和智能推荐
"""

from typing import Dict, Any, Optional, List
from datetime import datetime, timedelta
import uuid
from sqlalchemy.orm import Session as DBSession
from sqlalchemy.exc import SQLAlchemyError, IntegrityError
from src.utils.logging import get_logger
from src.utils.decorators import handle_errors, timing
from src.exceptions import UserNotFoundError, DatabaseError
from src.models.user import User
from src.models.user_preference import (
    UserPreference, 
    UserProfile, 
    UserPreferenceResponse, 
    UserProfileResponse,
    RecommendationItem,
    RecommendationsResponse,
    UserInterest,
    ContentItem,
    UserContentInteraction
)
from src.services.database_session_service import DatabaseSessionService

logger = get_logger(__name__)


class UserProfileService:
    """用户画像服务类"""
    
    def __init__(self, db_session: DBSession):
        self.db = db_session
        self.session_service = DatabaseSessionService(db_session)
    
    @handle_errors(default_return=None, log_level="ERROR")
    def get_user_preference(self, user_id: uuid.UUID) -> Optional[UserPreferenceResponse]:
        """
        获取用户偏好设置
        
        Args:
            user_id: 用户ID
            
        Returns:
            用户偏好响应
        """
        try:
            # 检查用户是否存在
            user = self.db.query(User).filter(User.id == user_id).first()
            if not user:
                raise UserNotFoundError(str(user_id))
            
            # 获取或创建用户偏好
            preference = self.db.query(UserPreference).filter(UserPreference.user_id == user_id).first()
            if not preference:
                # 创建默认偏好
                preference = self._create_default_preference(user_id)
            
            return UserPreferenceResponse.from_orm(preference)
        except UserNotFoundError:
            raise
        except SQLAlchemyError as e:
            logger.error(f"获取用户偏好失败: {e}", exc_info=True)
            raise DatabaseError(f"获取用户偏好失败: {str(e)}", operation="get_user_preference")
    
    def _create_default_preference(self, user_id: uuid.UUID) -> UserPreference:
        """创建默认用户偏好"""
        try:
            preference = UserPreference(user_id=user_id)
            self.db.add(preference)
            self.db.commit()
            self.db.refresh(preference)
            return preference
        except Exception as e:
            self.db.rollback()
            logger.error(f"创建默认用户偏好失败: {e}", exc_info=True)
            raise
    
    @handle_errors(default_return=None, log_level="ERROR")
    def update_user_preference(self, user_id: uuid.UUID, updates: Dict[str, Any]) -> UserPreferenceResponse:
        """
        更新用户偏好设置
        
        Args:
            user_id: 用户ID
            updates: 更新字段
            
        Returns:
            更新后的用户偏好响应
        """
        try:
            # 检查用户是否存在
            user = self.db.query(User).filter(User.id == user_id).first()
            if not user:
                raise UserNotFoundError(str(user_id))
            
            # 获取用户偏好
            preference = self.db.query(UserPreference).filter(UserPreference.user_id == user_id).first()
            if not preference:
                # 创建默认偏好
                preference = self._create_default_preference(user_id)
            
            # 更新字段
            for key, value in updates.items():
                if hasattr(preference, key) and value is not None:
                    setattr(preference, key, value)
            
            self.db.commit()
            self.db.refresh(preference)
            
            return UserPreferenceResponse.from_orm(preference)
        except UserNotFoundError:
            raise
        except SQLAlchemyError as e:
            self.db.rollback()
            logger.error(f"更新用户偏好失败: {e}", exc_info=True)
            raise DatabaseError(f"更新用户偏好失败: {str(e)}", operation="update_user_preference")
    
    @handle_errors(default_return=None, log_level="ERROR")
    def get_user_profile(self, user_id: uuid.UUID) -> Optional[UserProfileResponse]:
        """
        获取用户画像
        
        Args:
            user_id: 用户ID
            
        Returns:
            用户画像响应
        """
        try:
            # 检查用户是否存在
            user = self.db.query(User).filter(User.id == user_id).first()
            if not user:
                raise UserNotFoundError(str(user_id))
            
            # 获取或创建用户画像
            profile = self.db.query(UserProfile).filter(UserProfile.user_id == user_id).first()
            if not profile:
                # 创建默认画像
                profile = self._create_default_profile(user_id)
            
            return UserProfileResponse.from_orm(profile)
        except UserNotFoundError:
            raise
        except SQLAlchemyError as e:
            logger.error(f"获取用户画像失败: {e}", exc_info=True)
            raise DatabaseError(f"获取用户画像失败: {str(e)}", operation="get_user_profile")
    
    def _create_default_profile(self, user_id: uuid.UUID) -> UserProfile:
        """创建默认用户画像"""
        try:
            profile = UserProfile(
                user_id=user_id,
                interests=[],
                frequent_topics={},
                interaction_patterns={},
                sentiment_analysis={},
                preference_score={}
            )
            self.db.add(profile)
            self.db.commit()
            self.db.refresh(profile)
            return profile
        except Exception as e:
            self.db.rollback()
            logger.error(f"创建默认用户画像失败: {e}", exc_info=True)
            raise
    
    @handle_errors(log_level="ERROR")
    def update_user_profile(self, user_id: uuid.UUID, updates: Dict[str, Any]) -> UserProfileResponse:
        """
        更新用户画像
        
        Args:
            user_id: 用户ID
            updates: 更新字段
            
        Returns:
            更新后的用户画像响应
        """
        try:
            # 检查用户是否存在
            user = self.db.query(User).filter(User.id == user_id).first()
            if not user:
                raise UserNotFoundError(str(user_id))
            
            # 获取用户画像
            profile = self.db.query(UserProfile).filter(UserProfile.user_id == user_id).first()
            if not profile:
                # 创建默认画像
                profile = self._create_default_profile(user_id)
            
            # 更新字段
            for key, value in updates.items():
                if hasattr(profile, key) and value is not None:
                    setattr(profile, key, value)
            
            self.db.commit()
            self.db.refresh(profile)
            
            return UserProfileResponse.from_orm(profile)
        except UserNotFoundError:
            raise
        except SQLAlchemyError as e:
            self.db.rollback()
            logger.error(f"更新用户画像失败: {e}", exc_info=True)
            raise DatabaseError(f"更新用户画像失败: {str(e)}", operation="update_user_profile")
    
    @handle_errors(log_level="ERROR")
    def analyze_user_interactions(self, user_id: uuid.UUID, days: int = 30) -> Dict[str, Any]:
        """
        分析用户交互历史，更新用户画像
        
        Args:
            user_id: 用户ID
            days: 分析最近多少天的交互数据
            
        Returns:
            分析结果
        """
        try:
            # 检查用户是否存在
            user = self.db.query(User).filter(User.id == user_id).first()
            if not user:
                raise UserNotFoundError(str(user_id))
            
            # 获取用户会话
            from src.models.session import Session
            # 筛选最近N天的会话
            cutoff_date = datetime.utcnow() - timedelta(days=days)
            recent_sessions = self.db.query(Session).filter(
                Session.user_id == user_id,
                (Session.created_at >= cutoff_date) | (Session.updated_at >= cutoff_date)
            ).all()
            
            # 分析交互内容
            topic_frequency = {}
            sentiment_scores = {}
            interaction_count = 0
            
            for session in recent_sessions:
                # 获取会话历史
                interactions = self.session_service.get_session_history(session.id)
                # 确保 interactions 是列表类型
                if isinstance(interactions, list):
                    interaction_count += len(interactions)
                    
                    for interaction in interactions:
                        # 分析问题内容，提取关键词和主题
                        question = interaction.question
                        # 这里可以使用NLP工具提取关键词
                        # 简化实现：统计高频词
                        words = question.lower().split()
                        for word in words:
                            # 过滤停用词
                            if len(word) > 3 and word not in ['the', 'and', 'is', 'are', 'was', 'were', 'to', 'of', 'for', 'with', 'on', 'in', 'at']:
                                topic_frequency[word] = topic_frequency.get(word, 0) + 1
            
            # 计算用户画像
            # 排序主题频率
            sorted_topics = sorted(topic_frequency.items(), key=lambda x: x[1], reverse=True)
            top_10_topics = {k: v for k, v in sorted_topics[:10]}
            
            # 计算兴趣标签（这里简化处理）
            interests = []
            if top_10_topics:
                # 根据主题生成兴趣标签
                # 实际应用中可以使用更复杂的分类模型
                interests = [topic for topic, _ in sorted_topics[:5]]
            
            # 更新用户画像
            profile_updates = {
                'interests': interests,
                'frequent_topics': top_10_topics,
                'interaction_patterns': {
                    'total_interactions': interaction_count,
                    'session_count': len(recent_sessions),
                    'avg_interactions_per_session': interaction_count / len(recent_sessions) if recent_sessions else 0
                }
            }
            
            self.update_user_profile(user_id, profile_updates)
            
            return profile_updates
        except UserNotFoundError:
            raise
        except Exception as e:
            logger.error(f"分析用户交互失败: {e}", exc_info=True)
            raise DatabaseError(f"分析用户交互失败: {str(e)}", operation="analyze_user_interactions")
    
    @handle_errors(default_return=None, log_level="ERROR")
    def get_recommendations(self, user_id: uuid.UUID, limit: int = 5) -> RecommendationsResponse:
        """
        根据用户画像和历史行为生成个性化推荐
        
        Args:
            user_id: 用户ID
            limit: 推荐结果数量
            
        Returns:
            推荐结果响应
        """
        try:
            # 获取用户画像
            profile = self.db.query(UserProfile).filter(UserProfile.user_id == user_id).first()
            if not profile or not profile.interests:
                # 如果没有用户画像数据，返回通用推荐
                return self._get_generic_recommendations(limit)
            
            # 获取用户偏好
            preference = self.db.query(UserPreference).filter(UserPreference.user_id == user_id).first()
            
            # 根据兴趣和历史行为生成推荐
            recommendations = []
            
            # 基于用户兴趣生成知识推荐
            # 这里是简化实现，实际应用中可以连接知识库服务
            for i, interest in enumerate(profile.interests[:limit]):
                recommendation = RecommendationItem(
                    id=str(uuid.uuid4()),
                    type="knowledge",
                    title=f"关于{interest}的知识",
                    description=f"根据您的兴趣为您推荐的{interest}相关知识",
                    relevance_score=1.0 - (i * 0.1),
                    url=f"/knowledge?q={interest}",
                    tags=[interest, "推荐"]
                )
                recommendations.append(recommendation)
            
            # 如果有偏好的知识源，可以根据偏好调整推荐
            if preference is not None and preference.preferred_knowledge_sources is not None:
                # 这里可以添加基于知识源的推荐逻辑
                pass
            
            # 返回推荐结果
            return RecommendationsResponse(
                recommendations=recommendations,
                total_count=len(recommendations)
            )
        except Exception as e:
            logger.error(f"获取个性化推荐失败: {e}", exc_info=True)
            # 如果获取个性化推荐失败，返回通用推荐
            return self._get_generic_recommendations(limit)
    
    def _get_generic_recommendations(self, limit: int = 5) -> RecommendationsResponse:
        """返回通用推荐结果"""
        generic_recommendations = [
            RecommendationItem(
                id="1",
                type="service",
                title="智能客服助手使用指南",
                description="了解如何更好地使用我们的智能客服助手",
                relevance_score=0.8,
                url="/guide",
                tags=["指南", "入门"]
            ),
            RecommendationItem(
                id="2",
                type="knowledge",
                title="常见问题解答",
                description="查看最常见问题的解答",
                relevance_score=0.75,
                url="/faq",
                tags=["FAQ", "常见问题"]
            ),
            RecommendationItem(
                id="3",
                type="service",
                title="联系人工客服",
                description="如果您需要更深入的帮助，请联系我们的人工客服",
                relevance_score=0.7,
                url="/contact",
                tags=["人工客服", "帮助"]
            ),
            RecommendationItem(
                id="4",
                type="knowledge",
                title="最新功能介绍",
                description="了解我们最新推出的功能",
                relevance_score=0.65,
                url="/features",
                tags=["新功能", "更新"]
            ),
            RecommendationItem(
                id="5",
                type="knowledge",
                title="使用技巧分享",
                description="分享一些实用的使用技巧",
                relevance_score=0.6,
                url="/tips",
                tags=["技巧", "分享"]
            )
        ]
        
        return RecommendationsResponse(
            recommendations=generic_recommendations[:limit],
            total_count=len(generic_recommendations[:limit])
        )